﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Data.SqlClient;

namespace binary
{
    public partial class ImportTable : Form
    {
        public ConfigSingle config;
        public string fileDestination;
        public myDBF dbf;
        public SingleTable tableInfo;

        public Thread ReadThread;
        public Thread WriteThread;
        public Thread ProgressThread;

        public delegate void Proces();
        public delegate void Proces2(string tekst);
        public delegate void ProcesInt(int wartosc);
        public delegate void ProcesIntInt(int wartosc, int wartosc2);
        public delegate void ProcProgressBar(ProgressBar p, int wartosc, Label lbl);
        public delegate void ButtonDelegate(Button bt, bool value);

        DataTable fileContentCopy = new DataTable();
        DataTable fileContent = new DataTable();

        private bool IsReading {get;set;}
        private bool ReadAll {get;set;}
        public int RowsRead {get;set;}
        public int RowsWrite {get;set;}
        private int TableNumber {get;set;}
        private int Tables {get;set;}

        public ImportTable(ConfigSingle paramConfig, string paramFileDestination, SingleTable tableInfo, int paramTableNumber, int paramTables)
        {
            InitializeComponent();
            this.config = paramConfig;
            this.fileDestination = paramFileDestination;
            this.tableInfo = tableInfo;
            this.TableNumber = paramTableNumber;
            this.Tables = paramTables;
        }

        private void ImportTable_Load(object sender, EventArgs e)
        {
            this.ProgressThread = new Thread(new ThreadStart(Progress));
            this.ReadThread = new Thread(new ThreadStart(Read));
            this.WriteThread = new Thread(new ThreadStart(Write));
            lblTableName.Text = this.tableInfo.name;
            lblTables.Text = String.Format("{0} / {1}", this.TableNumber, this.Tables);
            ReadThread.Start();
        }

        public void Progress()
        {
            try
            {
                while (true)
                {
                    Thread.Sleep(100);
                    Invoke(new Proces(setProgres));
                }
            }
            catch (ThreadAbortException)
            {
                
            }
            catch(Exception)
            {
                //MessageBox.Show(ex.Message, "Postęp");
            }
        }

        private void setProgres()
        {
            try
            {
                if (progressRead.Maximum > 0)
                    lblRead.Text = String.Format("{0:N2} %", ((double)this.RowsRead / (double)progressRead.Maximum) * 100);
                if (progressWrite.Maximum > 0)
                    lblWrite.Text = String.Format("{0:N2} %", ((double)this.RowsWrite / (double)progressWrite.Maximum) * 100);
                this.progressWrite.Value = this.RowsWrite;
                this.progressRead.Value = this.RowsRead;
            }
            catch { }
        }

        private void Read()
        {
            this.IsReading = true;
            try
            {
                mySqlConnection p = new mySqlConnection(config);
                this.dbf = new myDBF(this.fileDestination, tableInfo.name);
                Invoke(new Proces(setRowsNumber));
                DataTable wynik = p.Query(String.Format("SELECT count(*) FROM INFORMATION_SCHEMA.tables WHERE TABLE_NAME = '{0}' and table_catalog = '{1}'", tableInfo.destinationName, config.dbName));
                Invoke(new Proces(setMaxProgressBar));
                ProgressThread.Start(); 

                if (int.Parse(wynik.Rows[0][0].ToString()) > 0)
                    p.QueryNoResult("truncate table " + tableInfo.destinationName);
                else
                    p.QueryNoResult(mySqlWorker.stworzTabele(dbf.Kolumny, tableInfo.destinationName));
                WriteThread.Start();
                this.dbf.pobierzDane(fileContent);
                ReadAll = true;
            }
            catch (ThreadAbortException)
            {}
            catch (Exception ex)
            {
                MessageBox.Show("Błąd wątku odczytu: " + ex.Message); 
            }
            
        }

        private void Write()
        {
            try
            {
                mySqlConnection p = new mySqlConnection(config);
                while (ReadAll == false || this.fileContent.Rows.Count > 0)
                {
                    if (this.fileContent.Rows.Count > 0)
                    {
                        Monitor.Enter(this.fileContent);
                        this.RowsRead += this.fileContent.Rows.Count;
                        this.fileContentCopy = this.fileContent.Copy();
                        this.fileContent.Clear();
                        var gags = (from x in fileContentCopy.AsEnumerable() select x.RowState).Distinct().ToList();
                        GC.Collect();
                        Monitor.Exit(this.fileContent);
                        using (SqlBulkCopy bulkCopy = new SqlBulkCopy(p.Connection))
                        {
                            bulkCopy.BulkCopyTimeout = 999999999;
                            bulkCopy.DestinationTableName = this.tableInfo.destinationName;

                            bulkCopy.WriteToServer(fileContentCopy);
                            RowsWrite = RowsWrite + fileContentCopy.Rows.Count;
                            fileContentCopy.Clear();
                            bulkCopy.Close();
                        }
                    }
                    Thread.Sleep(50);
                }
                ProgressThread.Abort(); 
                ProgressThread.Join();
                Invoke(new Proces(setProgres));
                Invoke(new Proces(closeForm));
            }
            catch (ThreadAbortException)
            {  }
            catch (Exception ex)
            {
                this.ProgressThread.Abort();
                this.ProgressThread.Join();
                this.ReadThread.Abort();
                this.ReadThread.Join();
                MessageBox.Show("Błąd zapisu: " + ex.Message);

                Invoke(new Proces(closeForm));
            }
        }

        public void setMaxProgressBar()
        {
            this.progressWrite.Maximum = this.dbf.LiczRekNieusunietych;
            this.progressRead.Maximum = this.dbf.LiczRekNieusunietych;
        }

        public void setRowsNumber()
        {
            lblRowsNumber.Text = String.Format("{0:N0}",this.dbf.LiczRekNieusunietych);
        }

        public void closeForm()
        {
            while (WriteThread.ThreadState == ThreadState.Running)
            {
                Thread.Sleep(100);
            }
            this.Close();
        }

        private void lblWrite_Click(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {

            if (WriteThread.ThreadState == ThreadState.Running || WriteThread.ThreadState == ThreadState.Suspended)
            {
                WriteThread.Abort();
                WriteThread.Join();
            }
            
            if (ProgressThread.ThreadState == ThreadState.Running || ProgressThread.ThreadState == ThreadState.Suspended)
            {
                ProgressThread.Abort();
                ProgressThread.Join();
            }
            
            if (ReadThread.ThreadState == ThreadState.Running || ReadThread.ThreadState == ThreadState.Suspended)
            {
                ReadThread.Abort();
                ReadThread.Join();
            }
            
            this.DialogResult = DialogResult.Abort;
            Close();
        }
    }
}
